#ifndef AURORA_TYPES_H
#define AURORA_TYPES_H

#include <boost/crc.hpp>      // for boost::crc_basic, boost::crc_optimal
#include <boost/cstdint.hpp>  // for boost::uint16_t
#include <boost/utility.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/variant.hpp>
#include <boost/smart_ptr.hpp>
#include <string>
#include <vector>

#include <tbb/concurrent_hash_map.h>
#include <tbb/concurrent_vector.h>

#include <borealis\Observation.hpp>
#include "VariableBase.hpp"
#include <borealis\AsciiRaster.hpp>


namespace AuroraTypes
{
	class AuroraHashCompare
	{
	public:
		static 	size_t hash( const std::string& x )
		{
			boost::crc_32_type crc32;
			std::string xlower = boost::algorithm::to_lower_copy<std::string>(x);
			crc32.process_bytes(xlower.c_str(),xlower.length());

			return crc32.checksum();
		}

		static bool equal( const std::string& s1, const std::string& s2 )
		{
			std::string ss1 = boost::algorithm::to_lower_copy<std::string>(s1);
			std::string ss2 = boost::algorithm::to_lower_copy<std::string>(s2);

			return ss1 == ss2;
		}
	};

	//the reason we are doing this is that we cant forward dec'l the one that contains the hashmap
	//so we dec'l the has class, forward dec'l modulebase
	//do the type defs
	//then normal declarations from herein
	class ModuleBase;
	
	typedef tbb::concurrent_vector< Borealis::Station*>										StationList;
	typedef tbb::concurrent_hash_map<std::string, boost::variant<boost::shared_ptr<Borealis::VariableBase>,std::string,int,double,float  >,AuroraHashCompare> VariableList;
	typedef std::vector<std::string>														InVariables;
	typedef std::vector<std::string>														OutVariables;
	typedef boost::tuple< std::vector<std::string>,std::vector<std::string>,ModuleBase*>	Module;
	
	class ModuleBase
	{
		
	public:
		std::string name;
		virtual void run(StationList* stations, VariableList* variables, InVariables& inVars, OutVariables& outVars)=0;

		virtual ~ModuleBase()
		{

		}
	};
	

	boost::shared_ptr<Borealis::Raster<float> > GetRaster(VariableList* variables,std::string& key);
	int GetInt(VariableList* variables,std::string& key);
	float GetFloat(VariableList* variables,std::string& key);
	double GetDouble(VariableList* variables,std::string& key);
	std::string GetString(VariableList* variables,std::string& key);
}

#endif